﻿using System;
using System.Drawing;
using System.Windows;

/*
    一条直线的表达式：Ax+By+C=0；A B 不同时为0就为有效
    斜截式表达式:y=kx+OffSet
已知两点p1,p2
A = Y2 - Y1
B = X1 - X2
C = X2*Y1 - X1*Y2
 */

namespace AutoUI
{
    public class AutoLine
    {
        #region Constructors

        /// <summary>
        /// 第一个点
        /// </summary>
        private readonly PointF p1;

        /// <summary>
        /// 第二个点
        /// </summary>
        private readonly PointF p2;

        private string _斜截表达式;

        private string _一般表达式;

        public AutoLine(PointF p1, PointF p2)
        {
            if (p1.X == p2.X && p1.Y == p2.Y)
            {
                p2.X += 1;
                p2.Y += 1;
            }
            A = p2.Y - p1.Y;
            B = p1.X - p2.X;
            C = p2.X * p1.Y - p1.X * p2.Y;
            if (A == 0)//平行x轴
            {
                斜截式表达式 = $"y={p1.Y}";
            }
            if (B == 0)//平行y轴
            {
                斜截式表达式 = $"x={p1.X}";
            }
            if (C == 0)//过原点
            {
            }
            this.p1 = p1;
            this.p2 = p2;
            this.angel = (float)(Math.Atan2(p1.Y - p2.Y, p2.X - p1.X) * SysConst.hudue);
            this.vector = new Vector(p2.X - p1.X, p1.Y - p2.Y);
        }

        public string 斜截式表达式
        {
            get { return _斜截表达式; }
            private set { _斜截表达式 = value; }
        }

        public string 一般表达式
        {
            get { return $"{A}x + {B}y + {C} = 0"; }
            private set { _一般表达式 = value; }
        }

        public override string ToString()
        {
            return $"一般表达式：{一般表达式}; \r\n斜截式表达式:{_斜截表达式}";
        }

        #endregion Constructors

        #region Properties

        private Vector vector;

        /// <summary>
        /// 这条线段的向量
        /// </summary>
        public Vector Vector
        {
            get { return vector; }
        }

        private float angel;

        /// <summary>
        /// 线段的角度(单位是 °)
        /// </summary>
        public float Angel
        {
            get { return angel; }
            // set { angel = value; }
        }

        /// <summary>
        /// 表达式：Ax+By+C=0中的A;
        /// A=0表示平行X轴
        /// </summary>
        public float A { get; set; }

        /// <summary>
        /// 表达式：Ax+By+C=0中的B
        /// B=0表示平行Y轴
        /// </summary>
        public float B { get; set; }

        /// <summary>
        /// 表达式：Ax+By+C=0中的C
        /// </summary>
        public float C { get; set; }

        /// <summary>
        ///
        /// </summary>
        public PointF EndPoint
        {
            get { return p2; }
        }

        /// <summary>
        /// 斜率
        /// </summary>
        public float K
        {
            get
            {
                if (B == 0)
                {
                    return float.MaxValue;
                }
                return -(A / B);
            }
        }

        /// <summary>
        /// 常数C(偏移)
        /// </summary>
        public float OffSet
        {
            get
            {
                if (B == 0)
                {
                    return p1.X;
                }
                return -(C / B);
            }
        }

        public PointF StartPoint
        {
            get { return p1; }
        }

        /// <summary>
        /// X轴截距,如果平行，结果为float.MaxValue
        /// </summary>
        public float XDistance
        {
            get
            {
                if (A == 0)
                {
                    return float.MaxValue;
                }
                return -(C / A);
            }
        }

        /// <summary>
        /// Y轴截距，如果平行y，结果为float.MaxValue
        /// </summary>
        public float YDistance
        {
            get
            {
                if (B == 0)
                {
                    return float.MaxValue;
                }
                return -(C / B);
            }
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// 获取两条直线的交点
        /// </summary>
        /// <param name="l1"></param>
        /// <param name="l2"></param>
        /// <returns></returns>
        public static PointF GetCrossPoint(AutoLine l1, AutoLine l2)
        {
            var denominator = l1.A * l2.B - l2.A * l1.B;
            var y = (l2.C * l1.A - l1.C * l2.A) / (l2.A * l1.B - l1.A * l2.B);
            var x = (l2.C * l1.B - l1.C * l2.B) / (l1.A * l2.B - l2.A * l1.B);
            return new PointF(x, y);
            // var x = (l2.B * l1.C - l1.B * l2.C) / denominator;
            //  var y = (l1.A * l2.C - l2.A * l1.C) / denominator;

            //if (l1.K == l2.K)//平行
            //{
            //    return new PointF(float.MaxValue, float.MaxValue);
            //}
            //if (l1.K == float.MaxValue)//第1条线垂直
            //{
            //    var y = l2.K * l1.OffSet + l2.OffSet;
            //    return new PointF(l1.OffSet, y);
            //}
            //if (l2.K == float.MaxValue)//第2条线垂直
            //{
            //    var y = l1.K * l2.OffSet + l1.OffSet;
            //    return new PointF(l2.OffSet, y);
            //}
            //if (l1.K == 0)//第1条线水平
            //{
            //}
            //if (l2.K == 0)//第2条线水平
            //{
            //    var x1 = (l2.OffSet - l1.OffSet) / l1.K;
            //    return new PointF(x1, l2.OffSet);
            //}
            //var x = (l2.C - l1.C) / (l1.K - l2.K);
            //return new PointF(x, l1.K * x + l1.C);
        }

        /// <summary>
        /// 获取两条直线的交点
        /// </summary>
        /// <param name="l"></param>
        /// <param name="l2"></param>
        /// <returns></returns>
        public PointF GetCrossPoint(AutoLine l)
        {
            return GetCrossPoint(this, l);
        }

        /// <summary>
        /// 根据y求x
        /// </summary>
        /// <param name="y"></param>
        /// <returns></returns>
        public float GetX(float y)
        {
            if (K == 0)
            {
                return float.MaxValue;
            }
            if (K == float.MaxValue)
            {
                return OffSet;
            }
            return (y - OffSet) / K;
        }

        /// <summary>
        /// 根据x求y
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public float GetY(float x)
        {
            if (K == float.MaxValue)
            {
                return float.MaxValue;
            }
            return K * x + OffSet;
        }

        /// <summary>
        /// 点到直线的距离，为正表示在线的下方，负表示在上方
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public float GetPointToLineDistance(PointF p)
        {
            var d = (A * p.X + B * p.Y + C) / Math.Sqrt(A * A + B * B);
            return (float)d;
        }

        /// <summary>
        /// 求点到直线的垂足
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public PointF Get垂足(PointF p)
        {
            var x = (B * B * p.X - A * B * p.Y - A * C) / (A * A + B * B);

            var y = (-A * B * p.X + A * A * p.Y - B * C) / (A * A + B * B);
            return new PointF(x, y);
        }

        #endregion Methods
    }
}